/*
 * Quercia Luciano
 * Algoritmi e Strutture Dati
 * a.a. 2009-10
 */


#ifndef _LISTA_H_
#define _LISTA_H_

#define SIZE 100

#include "nodoL.h"

template <class T>
class Lista
{
public:
	Lista();
	~Lista();

	typedef int posizione;

	//Operatori
	void creaLista();
	bool listaVuota();
	bool fineLista(posizione);
	posizione primoLista();
	posizione ultimoLista();
	posizione succLista(posizione);
	posizione precLista(posizione);
	T leggiLista(posizione) throw (char const *) ;
	void scriviLista(T, posizione) ;
	void insLista(T, posizione) ;
	void cancLista(posizione) ;

	//overloading operatori
	Lista operator+(Lista);


	//operatori personalizzati
	void print(void);
	void append( T );
	posizione direct( int );
	int sizeLista();

private:
	int lunghezza;
	NodoL<T> vettore[ SIZE ];
};



/*****************************
 *        DEFINIZIONI        *
 *     dei metodi di Lista   *
 *****************************/

template <class T>
Lista<T>::Lista() {
	creaLista();
}


template <class T>
Lista<T>::~Lista()
{}


template <class T>
void Lista<T>::creaLista() {
	lunghezza=0;
	T elementoNullo;
	for (int i=0; i<SIZE; i++) {
		vettore[i].setValue( elementoNullo );
		vettore[i].setPresente( false );
	}

}


template <class T>
bool Lista<T>::listaVuota() {
	return ( lunghezza == 0 );
}


template <class T>
bool Lista<T>::fineLista(posizione pos) {
	return ( ! vettore[ pos ].presente() );
}



template <class T>
int Lista<T>::sizeLista() {
	return lunghezza;
}


template <class T>
typename Lista<T>::posizione Lista<T>::primoLista() {
	return 0;
}


template <class T>
typename Lista<T>::posizione Lista<T>::ultimoLista() {
	if ( listaVuota() )
		return 0;
	else
		return (lunghezza-1);
}



template <class T>
typename Lista<T>::posizione Lista<T>::succLista( posizione pos ) {
	if ( ( pos+1 < SIZE ) && ( vettore[ pos+1 ].presente() ) )
		return (pos+1);
	else
		return pos;
}


template <class T>
typename Lista<T>::posizione Lista<T>::precLista( posizione pos ) {
	if ( pos == 0 )
		return pos;
	else if ( vettore[ pos-1 ].presente() )
		return (pos-1);
}


template <class T>
T Lista<T>::leggiLista(posizione pos) throw (char const *) {
	if ( vettore[pos].presente() )
		return(vettore[pos-1].getValue());
	else
		throw "Posizione non valida.";
}

template <class T>
void Lista<T>::scriviLista(T elem, posizione pos) {
	vettore[ pos ].setPresente(true);
	vettore[ pos ].setValue( elem );
}


template <class T>
void Lista<T>::insLista(T elem, posizione pos) {

	for ( int i=lunghezza; i>pos; i--) {
		vettore[i] = vettore[i-1];
	}

	vettore[lunghezza].setPresente(true);
	vettore[pos].setPresente(true);
	vettore[pos].setValue(elem);

	lunghezza++;

}

template <class T>
void Lista<T>::append( T elem ) {
	insLista( elem , lunghezza );
}


template <class T>
void Lista<T>::cancLista(posizione pos) {

	if ( vettore[pos].presente() ) {
		for ( int i=pos+1; i<lunghezza; i++) {
			vettore[i-1] = vettore[i];
		}
		vettore [ ultimoLista() ].setPresente( false );
		lunghezza--;
	} else {
		cout << "Impossibile eliminare l'elemento" << endl;
	}
}


template <class T>
void Lista<T>::print() {
	cout << "[ " ;
	for (int i=0; i<lunghezza; i++)
		cout << vettore[i].getValue() << " ";
	cout << "]" << endl;
}

template <class T>
typename Lista<T>::posizione Lista<T>::direct(int a) {
	if ( a > 0 )
		a--;

	if ( a == 0 )
		return a;

	if ( lunghezza != 0 )
		a = a % lunghezza ;

	if ( vettore[ a-1 ].presente() )
		return a;
	else
		return 0;
}

#endif
